package com.yunke.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunke.entity.YunkeScheduleJob;
import com.yunke.mapper.YunkeScheduleJobMapper;
import com.yunke.service.YunkeScheduleJobService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * 定时任务服务实现类
 * 
 * @author yunke
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class YunkeScheduleJobServiceImpl extends ServiceImpl<YunkeScheduleJobMapper, YunkeScheduleJob> 
        implements YunkeScheduleJobService {

    private final YunkeScheduleJobMapper scheduleJobMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createJob(YunkeScheduleJob job) {
        try {
            // 检查任务名称是否重复
            LambdaQueryWrapper<YunkeScheduleJob> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(YunkeScheduleJob::getJobName, job.getJobName())
                   .eq(YunkeScheduleJob::getJobGroup, job.getJobGroup())
                   .eq(YunkeScheduleJob::getStatus, 0);
            if (this.count(wrapper) > 0) {
                throw new RuntimeException("任务名称已存在");
            }

            // 设置默认值
            job.setJobStatus(0); // 暂停状态
            job.setExecuteCount(0);
            job.setSuccessCount(0);
            job.setFailCount(0);
            job.setRetryCount(0);
            job.setStatus(0);
            job.setCreateTime(System.currentTimeMillis());
            job.setUpdateTime(System.currentTimeMillis());

            return this.save(job);
            
        } catch (Exception e) {
            log.error("创建定时任务失败", e);
            throw new RuntimeException("创建定时任务失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateJob(YunkeScheduleJob job) {
        try {
            YunkeScheduleJob existingJob = this.getById(job.getId());
            if (existingJob == null || existingJob.getStatus() == 1) {
                throw new RuntimeException("任务不存在");
            }

            job.setUpdateTime(System.currentTimeMillis());
            return this.updateById(job);
            
        } catch (Exception e) {
            log.error("更新定时任务失败", e);
            throw new RuntimeException("更新定时任务失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteJob(Long id) {
        try {
            YunkeScheduleJob job = this.getById(id);
            if (job == null) {
                throw new RuntimeException("任务不存在");
            }

            // 如果任务正在运行，先停止任务
            if (job.getJobStatus() == 1) {
                stopJob(id);
            }

            job.setStatus(1);
            job.setUpdateTime(System.currentTimeMillis());
            return this.updateById(job);
            
        } catch (Exception e) {
            log.error("删除定时任务失败", e);
            throw new RuntimeException("删除定时任务失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean startJob(Long id) {
        try {
            // TODO: 启动定时任务
            log.info("启动定时任务: {}", id);
            return scheduleJobMapper.updateJobStatus(id, 1) > 0;
            
        } catch (Exception e) {
            log.error("启动定时任务失败", e);
            throw new RuntimeException("启动定时任务失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean stopJob(Long id) {
        try {
            // TODO: 停止定时任务
            log.info("停止定时任务: {}", id);
            return scheduleJobMapper.updateJobStatus(id, 0) > 0;
            
        } catch (Exception e) {
            log.error("停止定时任务失败", e);
            throw new RuntimeException("停止定时任务失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean pauseJob(Long id) {
        try {
            // TODO: 暂停定时任务
            log.info("暂停定时任务: {}", id);
            return scheduleJobMapper.updateJobStatus(id, 2) > 0;
            
        } catch (Exception e) {
            log.error("暂停定时任务失败", e);
            throw new RuntimeException("暂停定时任务失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resumeJob(Long id) {
        try {
            // TODO: 恢复定时任务
            log.info("恢复定时任务: {}", id);
            return scheduleJobMapper.updateJobStatus(id, 1) > 0;
            
        } catch (Exception e) {
            log.error("恢复定时任务失败", e);
            throw new RuntimeException("恢复定时任务失败：" + e.getMessage());
        }
    }

    public boolean executeJob(Long id) {
        try {
            YunkeScheduleJob job = this.getById(id);
            if (job == null || job.getStatus() == 1) {
                throw new RuntimeException("任务不存在");
            }

            // TODO: 立即执行一次任务
            log.info("立即执行定时任务: {}", id);
            
            return true;
            
        } catch (Exception e) {
            log.error("立即执行定时任务失败", e);
            throw new RuntimeException("立即执行定时任务失败：" + e.getMessage());
        }
    }

    @Override
    public IPage<YunkeScheduleJob> getJobPage(Integer current, Integer size, String jobName, 
                                             String jobGroup, Integer jobStatus) {
        Page<YunkeScheduleJob> page = new Page<>(current, size);
        
        LambdaQueryWrapper<YunkeScheduleJob> wrapper = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(jobName)) {
            wrapper.like(YunkeScheduleJob::getJobName, jobName);
        }
        
        if (StringUtils.hasText(jobGroup)) {
            wrapper.eq(YunkeScheduleJob::getJobGroup, jobGroup);
        }
        
        if (jobStatus != null) {
            wrapper.eq(YunkeScheduleJob::getStatus, jobStatus);
        }
        
        wrapper.orderByDesc(YunkeScheduleJob::getCreateTime);
        
        return this.page(page, wrapper);
    }

} 